//
//  NewBle.m
//  NewBle
//
//  Created by  on 2018/6/29.
//  Copyright © 2018年 杨赛. All rights reserved.
//

#import "NewBle.h"

#define SERVICE   @"FFF0"
#define SEND_CHAR @"FFF6"
#define REC_CHAR  @"FFF7"

@interface NewBle()<CBCentralManagerDelegate,CBPeripheralDelegate>
{
    
}
@end
@implementation NewBle
@synthesize CentralManage,PeripheralManager,activityPeripheral;
+(NewBle *)sharedManager
{
    static NewBle *sharedAccountManagerInstance = nil;
    static dispatch_once_t predicate;
    dispatch_once(&predicate, ^{
        sharedAccountManagerInstance = [[self alloc] init];
    });
    return sharedAccountManagerInstance;
}
//设置为主设备
- (void)SetUpCentralManager
{
    CentralManage = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
}
//设置为从设备
- (void)SetUpPeripheralManager
{
    
}

-(BOOL)isConnectOrConnecting
{
   if(activityPeripheral.state==CBPeripheralStateConnected||activityPeripheral.state==CBPeripheralStateConnecting)
        return YES;
    else
        return NO;
}

-(BOOL)isActivityPeripheral
{
   if(activityPeripheral.state==CBPeripheralStateConnected)
        return YES;
    else
        return NO;
}



- (void)startScanningWithServices:(nullable NSArray<CBUUID *> *)serviceUUIDs
{
    CentralManage.delegate = self;
    [CentralManage scanForPeripheralsWithServices:serviceUUIDs options:@{CBCentralManagerScanOptionAllowDuplicatesKey:@YES}];
}


- (void)connectDevice:(CBPeripheral*)peripheral
{
    if (CentralManage.isScanning==YES)
        [self Stopscan];
      activityPeripheral = peripheral;
      activityPeripheral.delegate = self;
      peripheral.delegate = self;
     [CentralManage connectPeripheral:peripheral options:nil];
}


#pragma mark 获取已经连接的设备
- (NSArray *)retrieveConnectedPeripheralsWithServices:(NSArray<CBUUID *> *)serviceUUIDs
{
    NSArray * arrayConnectPeripheral = [CentralManage retrieveConnectedPeripheralsWithServices:serviceUUIDs];
      return arrayConnectPeripheral;
}


#pragma mark 浮点转换
/*
 将浮点数f转化为4个字节数据存放在byte[4]中
 */
-(void)Float_to_Byte:(float)f byte:(Byte*)byte location:(int)location
{
    
    memcpy(byte+location, &f, 4);
    
}

#pragma mark 数据收发!!!
static void (^BLE_Block_Receive)(Byte* _Nullable buf,int length);

- (void)SendData:(char*)b length:(int)length
{
  
    int sam = 0;
    for (int j = 0; j < length; j++)
    {
        sam += b[j];
    }
    b[15] = sam;
    NSMutableData *data = [[NSMutableData alloc] initWithBytes:b length:length];
    
    [self writeValue:SERVICE characteristicUUID:SEND_CHAR p:activityPeripheral data:data];
    
}


-(void)writeValueUI:(NSString*)serviceUUID characteristicUUID:(NSString*)characteristicUUID p:(CBPeripheral *)p data:(NSData *)data
{
  
  
   
    CBService * service  = [self FindServiceFromUUID:serviceUUID Peripheral:p];
    if(!service)
    {
        NSLog(@"Could not find service with UUID %@ on peripheral",serviceUUID);
        return;
    }
    CBCharacteristic * characteristic = [self findCharacteristicFromUUID:characteristicUUID service:service];
    if(!characteristic)
    {
        NSLog(@"Could not find characteristic with UUID %@ on service with UUID %@ on peripheral",serviceUUID,characteristicUUID);
        return;
    }
    [p writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithoutResponse];  //ISSC
}
-(void)writeValue:(NSString*)serviceUUID characteristicUUID:(NSString*)characteristicUUID p:(CBPeripheral *)p data:(NSData *)data
{
  
    CBService * service  = [self FindServiceFromUUID:serviceUUID Peripheral:p];
    if(!service)
    {
        NSLog(@"Could not find service with UUID %@ on peripheral",serviceUUID);
        return;
    }
    CBCharacteristic * characteristic = [self findCharacteristicFromUUID:characteristicUUID service:service];
    if(!characteristic)
    {
        NSLog(@"Could not find characteristic with UUID %@ on service with UUID %@ on peripheral",serviceUUID,characteristicUUID);
        return;
    }
    [p writeValue:data forCharacteristic:characteristic type:CBCharacteristicWriteWithResponse];  //ISSC
}


- (void)retrieveConnectedPeripheralsWithServices:(NSArray<CBUUID *> *)serviceUUIDs Block:(void (^)(NSArray* arrayConnectPeripheral,BOOL isSuccess))block
{
    NSArray * arrayConnectPeripheral = [CentralManage retrieveConnectedPeripheralsWithServices:serviceUUIDs];
    if(arrayConnectPeripheral.count>0)
        block(arrayConnectPeripheral,YES);
    else
        block(nil,NO);
}

-(void)Stopscan
{
    [CentralManage stopScan];
}
-(void)Disconnect
{
    if(activityPeripheral)
    [CentralManage cancelPeripheralConnection:activityPeripheral];
}

-(void)enable
{
    [self notification:SERVICE characteristicUUID:REC_CHAR p:activityPeripheral on:YES];
}

-(void)notification:(NSString*)serviceUUID characteristicUUID:(NSString*)characteristicUUID p:(CBPeripheral *)p on:(BOOL)on
{
   CBService * service  = [self FindServiceFromUUID:serviceUUID Peripheral:p];
    if(!service)
    {
        NSLog(@"Could not find service with UUID %@ on peripheral",serviceUUID);
        return;
    }
    CBCharacteristic * characteristic = [self findCharacteristicFromUUID:characteristicUUID service:service];
    if(!characteristic)
    {
        NSLog(@"Could not find characteristic with UUID %@ on service with UUID %@ on peripheral",serviceUUID,characteristicUUID);
        return;
    }
   [p setNotifyValue:on forCharacteristic:characteristic];
   [self.delegate EnableCommunicate];
}


-(CBService*)FindServiceFromUUID:(NSString*)serviceUUID Peripheral:(CBPeripheral *)peripheral
{
    
    for (int i = 0; i<peripheral.services.count; i++) {
        CBService * service = [peripheral.services objectAtIndex:i];
        if([service.UUID.UUIDString.lowercaseString isEqualToString:serviceUUID.lowercaseString])
            return service;
    }
    return nil;
}

//查找服务的指定特征
-(CBCharacteristic *) findCharacteristicFromUUID:(NSString *)UUID service:(CBService*)service {
    for(int i=0; i < service.characteristics.count; i++) {
        CBCharacteristic *c = [service.characteristics objectAtIndex:i];
        if([UUID.lowercaseString isEqualToString:c.UUID.UUIDString.lowercaseString])
            return c;
    }
    return nil; //Characteristic not found on this service
}


#pragma mark 蓝牙状态发生改变
-(NSString*)centralManagerStateToString:(NSInteger)state
{
    switch(state) {
        case CBManagerStateUnknown:
            return @"CBManagerStateUnknown";
        case CBManagerStateResetting:
            return @"CBManagerStateResetting";
        case CBManagerStateUnsupported:
            return @"CBManagerStateUnsupported";
        case CBManagerStateUnauthorized:
            return @"CBManagerStateUnauthorized";
        case CBManagerStatePoweredOff:
        {
            [[NSUserDefaults standardUserDefaults] setBool:NO forKey:@"blestatus"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            [self.delegate Disconnect:nil];
            return @"CBCentralManagerStatePoweredOff";
        }
        case CBManagerStatePoweredOn:
        {
            [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"blestatus"];
            [[NSUserDefaults standardUserDefaults] synchronize];
            return @"CBCentralManagerStatePoweredOn";
        }
        default:
            return @"State unknown";
    }
    return @"Unknown state";
}
#pragma mark CBCentralManagerDelegate
- (void)centralManagerDidUpdateState:(nonnull CBCentralManager *)central {
    NSLog(@"Status of CoreBluetooth central manager changed %@",[self centralManagerStateToString:central.state]);
}

- (void)centralManager:(CBCentralManager *)central willRestoreState:(NSDictionary<NSString *, id> *)dict
{
    
}
- (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary<NSString *, id> *)advertisementData RSSI:(NSNumber *)RSSI
{
    [self.delegate scanWithPeripheral:peripheral advertisementData:advertisementData RSSI:RSSI];
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral
{
    [peripheral discoverServices:nil];
    [self.delegate ConnectSuccessfully];
}
    
- (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error
{
    
    
    [self.delegate ConnectFailedWithError:error];
}
- (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(nullable NSError *)error
{

    if(error)
    {
        [central connectPeripheral:peripheral options:nil];
    }
     [self.delegate Disconnect:error];
}
#pragma mark CBPeripheralDelegate
- (void)peripheralDidUpdateName:(CBPeripheral *)peripheral
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didModifyServices:(NSArray<CBService *> *)invalidatedServices NS_AVAILABLE(10_9, 7_0)
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didReadRSSI:(NSNumber *)RSSI error:(nullable NSError *)error NS_AVAILABLE(10_13, 8_0)
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(nullable NSError *)error
{
    for (int i=0; i < peripheral.services.count; i++) {
        CBService *s = [peripheral.services objectAtIndex:i];
        [peripheral discoverCharacteristics:nil forService:s];
    }
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverIncludedServicesForService:(CBService *)service error:(nullable NSError *)error
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(nullable NSError *)error
{
    if([service isEqual:peripheral.services.lastObject])
        [self enable];
    
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
{
    //    NSLog(@"characteristic.value --- : %@",characteristic.value);
    NSString * strUUID = characteristic.UUID.UUIDString;
    if([strUUID isEqualToString:REC_CHAR])
    {
        Byte *byte = (Byte *)[characteristic.value bytes];
        if (byte[0]==CMD_SET_DEVICE_INFO)
            !BLE_Block_Receive?:BLE_Block_Receive(byte,(int)characteristic.value.length);
        
        [self.delegate BleCommunicateWithPeripheral:peripheral byte:byte dataLength:characteristic.value.length];
    }
}
 - (void)peripheral:(CBPeripheral *)peripheral didWriteValueForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didDiscoverDescriptorsForCharacteristic:(CBCharacteristic *)characteristic error:(nullable NSError *)error
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didWriteValueForDescriptor:(CBDescriptor *)descriptor error:(nullable NSError *)error
{
    
}
- (void)peripheralIsReadyToSendWriteWithoutResponse:(CBPeripheral *)peripheral
{
    
}
- (void)peripheral:(CBPeripheral *)peripheral didOpenL2CAPChannel:(nullable CBL2CAPChannel *)channel error:(nullable NSError *)error
API_AVAILABLE(ios(11.0)){
    
}


-(void)SetDeviceBasicParameters:(NSMutableArray*_Nullable)arrayBasicParameters WithBlock:(void (^_Nullable)(Byte* _Nullable buf,int length))block
{
    BLE_Block_Receive = block;
    char b[] = {CMD_SET_DEVICE_INFO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    for (int i = 0; i<arrayBasicParameters.count; i++) {
        NSNumber * number = arrayBasicParameters[i];
        b[i+1] = number.intValue;
    }
    [self SendData:b length:16];
}

-(void)CheckTime:(MyDeviceTime)deviceTime Block:(void (^_Nullable)(Byte* _Nullable buf,int length))block
{
    BLE_Block_Receive = block ;
    int year = (deviceTime.year-2000)+((deviceTime.year-2000)/10*6);
    int month = deviceTime.month + (deviceTime.month/10*6) ;
    int day = deviceTime.day + (deviceTime.day/10*6) ;
    int hour = deviceTime.hour + (deviceTime.hour/10*6) ;
    int minute = deviceTime.minute + (deviceTime.minute/10*6) ;
    int seconds = deviceTime.second + (deviceTime.second/10*6) ;
    
    char b[] = {CMD_SET_TIME,year,month,day,hour,minute,seconds,0,0,0,0,0,0,0,0,0};
    if(deviceTime.TimeZone>0)
    {
        b[9] = 0x80 +deviceTime.TimeZone/256;
        b[8] = deviceTime.TimeZone%256;
    }
    else
    {
        b[9] = -deviceTime.TimeZone/256;
        b[8] = -deviceTime.TimeZone%256;
    }
    [self SendData:b length:16];
}

-(void)SetOnlineWatchDeviceBasicParametersWithBlock:(void (^_Nullable)(Byte* _Nullable buf,int length))block
{
    BLE_Block_Receive = block;
    char b[] = {CMD_SET_DEVICE_INFO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        b[12] = 0X8A;
    
    [self SendData:b length:16];
}

-(void)Set_2051_OnlineWatchDeviceBasicParametersWithBlock:(void (^_Nullable)(Byte* _Nullable buf,int length))block
{
    BLE_Block_Receive = block;
    char b[] = {CMD_SET_DEVICE_INFO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        b[12] = 0X88;
    
    [self SendData:b length:16];
}

-(void)Set_1963YH_OnlineWatchDeviceBasicParametersWithBlock:(void (^_Nullable)(Byte* _Nullable buf,int length))block
{
    BLE_Block_Receive = block;
    char b[] = {CMD_SET_DEVICE_INFO,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
        b[12] = 0xca;
    
    [self SendData:b length:16];
}

@end

